﻿using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace VMExplorer.Win32
{
  // Processes
  partial class Native
  {
    #region :: Enums ::

    public enum PROCESSINFOCLASS : int
    {
      ProcessBasicInformation = 0,
      ProcessQuotaLimits,
      ProcessIoCounters,
      ProcessVmCounters,
      ProcessTimes,
      ProcessBasePriority,
      ProcessRaisePriority,
      ProcessDebugPort,
      ProcessExceptionPort,
      ProcessAccessToken,
      ProcessLdtInformation,
      ProcessLdtSize,
      ProcessDefaultHardErrorMode,
      ProcessIoPortHandlers, // Note: this is kernel mode only
      ProcessPooledUsageAndLimits,
      ProcessWorkingSetWatch,
      ProcessUserModeIOPL,
      ProcessEnableAlignmentFaultFixup,
      ProcessPriorityClass,
      ProcessWx86Information,
      ProcessHandleCount,
      ProcessAffinityMask,
      ProcessPriorityBoost,
      MaxProcessInfoClass,
      ProcessWow64Information = 26
    };

    [Flags]
    public enum ProcessParametersFlags : uint
    {
      NORMALIZED = 0x01,
      PROFILE_USER = 0x02,
      PROFILE_SERVER = 0x04,
      PROFILE_KERNEL = 0x08,
      UNKNOWN = 0x10,
      RESERVE_1MB = 0x20,
      DISABLE_HEAP_CHECKS = 0x100,
      PROCESS_OR_1 = 0x200,
      PROCESS_OR_2 = 0x400,
      PRIVATE_DLL_PATH = 0x1000,
      LOCAL_DLL_PATH = 0x2000,
      NX = 0x20000,
    }

    #endregion
    #region :: Structs ::

    [StructLayout (LayoutKind.Sequential, Size = 0x18)]
    public struct PROCESS_BASIC_INFORMATION
    {
      public Int32 ExitStatus;
      public IntPtr PebBaseAddress;
      public UInt32 AffinityMask;
      public UInt32 BasePriority;
      public UInt32 UniqueProcessId;
      public UInt32 InheritedFromUniqueProcessId;
    };

    [StructLayout (LayoutKind.Explicit, Size = 0x20C)]
    public struct PEB
    {
      [FieldOffset (0x000)]
      public byte InheritedAddressSpace;
      [FieldOffset (0x001)]
      public byte ReadImageFileExecOptions;
      [FieldOffset (0x002)]
      public byte BeingDebugged;
      [FieldOffset (0x003)]
      public byte Spare;
      [FieldOffset (0x004)]
      public HANDLE Mutant;
      [FieldOffset (0x008)]
      public IntPtr ImageBaseAddress; // (PVOID) 
      [FieldOffset (0x00c)]
      public IntPtr LoaderData; // (PPEB_LDR_DATA)
      [FieldOffset (0x010)]
      public IntPtr ProcessParameters; // (PRTL_USER_PROCESS_PARAMETERS)
      [FieldOffset (0x014)]
      public IntPtr SubSystemData;  // (PVOID) 
      [FieldOffset (0x018)]
      public IntPtr ProcessHeap;  // (PVOID) 
      [FieldOffset (0x01c)]
      public IntPtr FastPebLock; // (PRTL_CRITICAL_SECTION)  
      [FieldOffset (0x020)]
      public IntPtr FastPebLockRoutine; // (PPEBLOCKROUTINE)
      [FieldOffset (0x024)]
      public IntPtr FastPebUnlockRoutine;  // (PPEBLOCKROUTINE)
      [FieldOffset (0x028)]
      public UInt32 EnvironmentUpdateCount; // (ULONG)
      [FieldOffset (0x02c)]
      public IntPtr KernelCallbackTable;  // (PPVOID)  
      [FieldOffset (0x030)]
      public IntPtr SystemReserved;  // (PVOID)  
      [FieldOffset (0x034)]
      public IntPtr AtlThunkSListPtr32;  // (PVOID)  
      [FieldOffset (0x038)]
      public IntPtr FreeList;  // (PPEB_FREE_BLOCK) 
      [FieldOffset (0x03c)]
      public UInt32 TlsExpansionCounter;  // (ULONG) 
      [FieldOffset (0x040)]
      public IntPtr TlsBitmap;  // (PVOID)
      [MarshalAs (UnmanagedType.ByValArray, SizeConst = 2)]
      [FieldOffset (0x044)]
      public UInt32 [] TlsBitmapBits;  // (ULONG) 
      [FieldOffset (0x04c)]
      public IntPtr ReadOnlySharedMemoryBase;  // (PVOID) 
      [FieldOffset (0x050)]
      public IntPtr ReadOnlySharedMemoryHeap;  // (PVOID) 
      [FieldOffset (0x054)]
      public IntPtr ReadOnlyStaticServerData;  // (PPVOID) 
      [FieldOffset (0x058)]
      public IntPtr AnsiCodePageData;  // (PVOID) 
      [FieldOffset (0x05c)]
      public IntPtr OemCodePageData;  // (PVOID) 
      [FieldOffset (0x060)]
      public IntPtr UnicodeCaseTableData;  // (PVOID) 
      [FieldOffset (0x064)]
      public UInt32 NumberOfProcessors;  // (ULONG) 
      [FieldOffset (0x068)]
      public UInt32 NtGlobalFlag;  // (ULONG) 
      [FieldOffset (0x070)]
      public Int64 CriticalSectionTimeout;  // (LARGE_INTEGER) 
      [FieldOffset (0x078)]
      public UInt32 HeapSegmentReserve;  // (ULONG) 
      [FieldOffset (0x07c)]
      public UInt32 HeapSegmentCommit;  // (ULONG) 
      [FieldOffset (0x080)]
      public UInt32 HeapDeCommitTotalFreeThreshold;  // (ULONG) 
      [FieldOffset (0x084)]
      public UInt32 HeapDeCommitFreeBlockThreshold;  // (ULONG) 
      [FieldOffset (0x088)]
      public UInt32 NumberOfHeaps;  // (ULONG) 
      [FieldOffset (0x08c)]
      public UInt32 MaximumNumberOfHeaps;  // (ULONG) 
      [FieldOffset (0x090)]
      public IntPtr ProcessHeaps;  // (PHEAP*) 
      [FieldOffset (0x094)]
      public IntPtr GdiSharedHandleTable;  // (PVOID) 
      [FieldOffset (0x098)]
      public IntPtr ProcessStarterHelper;  // (PVOID) 
      [FieldOffset (0x09c)]
      public IntPtr GdiDCAttributeList;  // (PVOID) 
      [FieldOffset (0x0a0)]
      public IntPtr LoaderLock;  // (PVOID) 
      [FieldOffset (0x0a4)]
      public UInt32 OSMajorVersion;  // (ULONG) 
      [FieldOffset (0x0a8)]
      public UInt32 OSMinorVersion;  // (ULONG) 
      [FieldOffset (0x0ac)]
      public UInt16 OSBuildNumber;  // (ULONG) 
      [FieldOffset (0x0ae)]
      public UInt16 OSCSDVersion;  // (ULONG) 
      [FieldOffset (0x0b0)]
      public UInt32 OSPlatformId;  // (ULONG) 
      [FieldOffset (0x0b4)]
      public UInt32 ImageSubSystem;   // (ULONG)
      [FieldOffset (0x0b8)]
      public UInt32 ImageSubSystemMajorVersion;   // (ULONG)
      [FieldOffset (0x0bc)]
      public UInt32 ImageSubSystemMinorVersion;  // (ULONG)  
      [FieldOffset (0x0c0)]
      public UInt32 ImageProcessAffinityMask;  // (ULONG)  
      [MarshalAs (UnmanagedType.ByValArray, SizeConst = 0x22)]
      [FieldOffset (0x0c4)]
      public UInt32 [] GdiHandleBuffer;  // (ULONG)   
      [FieldOffset (0x14c)]
      public UInt32 PostProcessInitRoutine;  // (ULONG) 
      [FieldOffset (0x150)]
      public IntPtr TlsExpansionBitmap;  // (ULONG)       
      [MarshalAs (UnmanagedType.ByValArray, SizeConst = 0x80)]
      [FieldOffset (0x154)]
      public byte [] TlsExpansionBitmapBits;  // (BYTE) 
      [FieldOffset (0x1d4)]
      public UInt32 SessionId;  // (ULONG)
      [FieldOffset (0x1d8)]
      public UInt64 AppCompatFlags;
      [FieldOffset (0x1e0)]
      public UInt64 AppCompatFlagsUser;
      [FieldOffset (0x1e8)]
      public IntPtr pShimData;
      [FieldOffset (0x1ec)]
      public IntPtr AppCompatInfo;
      [FieldOffset (0x1f0)]
      public UNICODE_STRING CSDVersion;
      [FieldOffset (0x1f8)]
      public IntPtr ActivationContextData;
      [FieldOffset (0x1fc)]
      public IntPtr ProcessAssemblyStorageMap;
      [FieldOffset (0x200)]
      public IntPtr SystemDefaultActivationContextData;
      [FieldOffset (0x204)]
      public IntPtr SystemAssemblyStorageMap;
      [FieldOffset (0x208)]
      public UInt32 MinimumStackCommit;
    };

    [StructLayout (LayoutKind.Sequential, Size = 0x2C)]
    public struct PEB_LDR_DATA
    {
      public UInt32 Length;
      public Byte Initialized;
      public HANDLE SsHandle;
      public LIST_ENTRY InLoadOrderModuleList;
      public LIST_ENTRY InMemoryOrderModuleList;
      public LIST_ENTRY InInitializationOrderModuleList;
      public IntPtr EntryInProgress;
    };

    [StructLayout (LayoutKind.Sequential, Size = 0x48)]
    public struct LDR_MODULE
    {
      public LIST_ENTRY InLoadOrderModuleList;
      public LIST_ENTRY InMemoryOrderModuleList;
      public LIST_ENTRY InInitializationOrderModuleList;
      public IntPtr BaseAddress;
      public IntPtr EntryPoint;
      public UInt32 SizeOfImage;
      public UNICODE_STRING FullDllName;
      public UNICODE_STRING BaseDllName;
      public UInt32 Flags;
      public Int16 LoadCount;
      public Int16 TlsIndex;
      public LIST_ENTRY HashTableEntry;
      public UInt32 TimeDateStamp;
    }

    [StructLayout (LayoutKind.Sequential, Size = 0x290)]
    public struct RTL_USER_PROCESS_PARAMETERS
    {
      public UInt32 MaximumLength;
      public UInt32 Length;
      public ProcessParametersFlags Flags;
      public UInt32 DebugFlags;
      public HANDLE ConsoleHandle;
      public UInt32 ConsoleFlags;
      public HANDLE StdInputHandle;
      public HANDLE StdOutputHandle;
      public HANDLE StdErrorHandle;
      public UNICODE_STRING CurrentDirectoryPath;
      public HANDLE CurrentDirectoryHandle;
      public UNICODE_STRING DllPath;
      public UNICODE_STRING ImagePathName;
      public UNICODE_STRING CommandLine;
      public IntPtr Environment; // PVOID
      public UInt32 StartingPositionLeft;
      public UInt32 StartingPositionTop;
      public UInt32 Width;
      public UInt32 Height;
      public UInt32 CharWidth;
      public UInt32 CharHeight;
      public UInt32 ConsoleTextAttributes;
      public UInt32 WindowFlags;
      public UInt32 ShowWindowFlags;
      public UNICODE_STRING WindowTitle;
      public UNICODE_STRING DesktopName;
      public UNICODE_STRING ShellInfo;
      public UNICODE_STRING RuntimeData;
      [MarshalAs (UnmanagedType.ByValArray, SizeConst = 0x20)]
      public RTL_DRIVE_LETTER_CURDIR [] DLCurrentDirectory;
    };

    #endregion
    #region :: API ::

    [DllImport ("ntdll.dll", SetLastError = true)]
    public static extern UInt32 NtQueryInformationProcess (SafeProcessHandle ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, IntPtr ProcessInformation, UInt32 ProcessInformationLength, ref UInt32 ReturnLength);

    [DllImport ("ntdll.dll", SetLastError = true)]
    public static extern UInt32 NtSuspendProcess (SafeProcessHandle ProcessHandle);

    [DllImport ("ntdll.dll", SetLastError = true)]
    public static extern UInt32 NtResumeProcess (SafeProcessHandle ProcessHandle);

    [DllImport ("kernel32.dll")]
    public static extern SafeProcessHandle OpenProcess (ProcessAccess desiredAccess, [MarshalAs (UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);

    #endregion
  }
}